#ifndef MULTINET_H_
#define MULTINET_H_
/*********************************************************/
// 224.0.0.1 All hosts multicast address
// 239.0.0.0/8 free use multicasting addresses
#include <Poco/Net/MulticastSocket.h>
#include <Poco/Net/NetworkInterface.h>
#include <Poco/Runnable.h>
#include <Poco/Thread.h>
#include <Poco/Mutex.h>

#include <queue>
#include <string>

#define MULTI_PACKET_SIZE_LIMIT 65507		// Theoretical maximum size of a multicast datagram packet
#define EXIT_GROUP "239.0.0.1"
// Ports 0 - 1023 are IANA controlled ports
// 1024 - 65535 are available for registration by 'normal' users
/*********************************************************/
/** This Class provides an easy to use, multithreaded interface to a broadcasting socket **/
class MultiNet : public Poco::Runnable
{
private:
	// Variables
	Poco::Net::MulticastSocket	*sock;			// Multicastsocket used for multicast traffic
	Poco::Net::IPAddress 		groupip;		// Multicast group
	Poco::Net::NetworkInterface	netInt;			// Network interface
	Poco::Thread			lThread;		// Local thread handle
	mutable Poco::Mutex		mutex;			// Mutual Exclusion synch object
	std::queue<std::string>		data;			// Stores all received data
	std::string			eventStr;		// Event to flag when data is received
	bool				group;			// Did the socket join a multicasting group?
	bool				halt;			// Is the thread requested to halt?
	int 				port;			// Port the socket is bound to

	// Methods
	void run();						// Thread entry point

protected:
	// Methods
	MultiNet(const MultiNet&) {};				// Copy Construction is forbidden

public:
	// Methods for group control
	void leaveGroup();					// Leave the multicasting group
	void joinGroup(const std::string&, unsigned int);	// Joins a multicasting group
	std::string getGroupIP() const;				// Returns the ip of the current multicast group
	int getGroupPort() const;

	// Methods for class control
	void start(const std::string&);				// Start the class thread
	void stop();						// Stop the class thread

	// Methods for sending & retrieving messages
	void send(const std::string&);				// Send a string message accross the network
	bool available();					// returns true if data is waiting in the queue
	std::string pop();					// Pop the next message off the message queue
	std::string peek();					// Peek at the next message in the message queue
	void setLoopback(bool);					// enables loopback of multicast messages

	// Constructor & Destructor
	MultiNet(const std::string&);				// Constructor with interface specification
	MultiNet();						// Constructor withot interface specification ( uses default one )
	~MultiNet();						// Destructs the class
};
/*********************************************************/
#endif // MULTINET_H_
